package com.qriver.gateway.filter;

import java.nio.charset.StandardCharsets;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;

import com.alibaba.fastjson.JSONObject;
import com.qriver.auth.client.config.UserAuthConfig;
import com.qriver.auth.client.utils.UserAuthUtil;
import com.qriver.auth.common.utils.jwt.IJWTInfo;
import com.qriver.common.context.BaseContextHandler;
import com.qriver.gateway.feign.IUserService;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class AccessGatewayFilter implements GlobalFilter, Ordered{

	@Autowired
	private IUserService userService;
	@Autowired
    private UserAuthConfig userAuthConfig;//参数配置，token在header的key和pubKeyByte
	@Autowired
    private UserAuthUtil userAuthUtil;//根据token获取IJWTInfo
	
	private String whiteList = "/token";
	
	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		ServerHttpRequest request = exchange.getRequest();
	    String requestUri = request.getPath().pathWithinApplication().value();
	    //final String requestMethod = request.getMethod().toString();
        BaseContextHandler.setToken(null);
        ServerHttpRequest.Builder builder = request.mutate();
        if(isIgnoreLoginCheck(requestUri)) {//白名单，免验证
        	ServerHttpRequest httpRequest = builder.build();
        	return chain.filter(exchange.mutate().request(httpRequest).build());
        }
        IJWTInfo user = null;
        try {//获取用户信息
            user = getJWTUser(request, builder);
        } catch (Exception e) {
            System.out.println("用户Token过期异常");
            return getVoidMono(exchange, "User Token Forbidden or Expired!");
        }
        //验证对该链接是否有访问权限
        if(!checkUserPermission(exchange, user)) {
        	return getVoidMono(exchange, "User Forbidden!Does not has Permission!");
        }
        ServerHttpRequest build = builder.build();
		return chain.filter(exchange.mutate().request(build).build());
	}
	/**
	 * 判断当前用户，是否有访问该接口权限。（本方法是临时的方法）
	 * @param ctx
	 * @param user
	 * @return
	 */
	 private boolean checkUserPermission(ServerWebExchange ctx, IJWTInfo user) {
		 boolean flag = true;
		 String result = userService.authentication(user.getUniqueName());
		 if("true".equalsIgnoreCase(result)) {
			 flag = true;
		 }else {
			 flag = false;
		 }
		 return flag;
	 }
	/**
              * 网关抛异常
     *
     * @param body
     */
    private Mono<Void> getVoidMono(ServerWebExchange serverWebExchange, String body) {
        serverWebExchange.getResponse().setStatusCode(HttpStatus.OK);
        byte[] bytes = JSONObject.toJSONString(body).getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = serverWebExchange.getResponse().bufferFactory().wrap(bytes);
        return serverWebExchange.getResponse().writeWith(Flux.just(buffer));
    }
    /**
             * 获取用户信息
     * @param request
     * @param ctx
     * @return
     * @throws Exception
     */
	private IJWTInfo getJWTUser(ServerHttpRequest request, ServerHttpRequest.Builder ctx) throws Exception {
        List<String> strings = request.getHeaders().get(userAuthConfig.getTokenHeader());
        String authToken = null;
        if (strings != null) {
            authToken = strings.get(0);
        }
        if (StringUtils.isBlank(authToken)) {
            strings = request.getQueryParams().get("token");
            if (strings != null) {
                authToken = strings.get(0);
            }
        }
        ctx.header(userAuthConfig.getTokenHeader(), authToken);
        BaseContextHandler.setToken(authToken);
        return userAuthUtil.getInfoFromToken(authToken);
    }
	private boolean isIgnoreLoginCheck(String requestUri) {
		boolean flag = false;
        for (String s : whiteList.split(",")) {
            if (requestUri.startsWith(s)) {
                return true;
            }
        }
        return flag;
	}
	
	
	
	@Override
	public int getOrder() {
		return 0;
	}

}
